import { useRef } from 'react';

// 存储 Form 的数据
export class FormStore {
  constructor() {
    // 存储 form 要处理的数据
    this.store = {};
    // 存储 field
    this.fieldEntities = {};
    this.callbacks = {};
  }

  setCallback = (callbacks) => {
    this.callbacks = {
      ...this.callbacks,
      ...callbacks,
    };
  };

  // 注册
  registerEntity = (entity) => {
    this.fieldEntities = {
      ...this.fieldEntities,
      [entity.props.name]: entity,
    };

    // 取消注册
    return () => {
      delete this.fieldEntities[entity.props.name];
    };
  };

  setFieldsValue = (newStore) => {
    // 更新保存的数据
    this.store = {
      ...this.store,
      ...newStore,
    };

    // 更新组件
    Object.keys(newStore).forEach((name) => {
      this.fieldEntities[name].onStoreChange();
    });
  };

  getFieldValue = (fieldName) => {
    return this.store[fieldName];
  };

  validate = () => {
    let err = [];

    // 遍历 store
    Object.keys(this.fieldEntities).forEach((key) => {
      const value = this.getFieldValue(key);
      const entity = this.fieldEntities[key];
      const { rules = [] } = entity.props;
      const rule = rules[0];
      if (rule && rule.required && (value === undefined || value === '')) {
        err.push({ [key]: rule.message, value });
      }
    });

    return err;
  };

  submit = () => {
    const err = this.validate();
    const { onFinish, onFinishFailed } = this.callbacks;

    if (!err.length) {
      onFinish && onFinish({ ...this.store });
    } else {
      onFinishFailed && onFinishFailed({ err, store: { ...this.store } });
    }
  };

  getForm = () => {
    return {
      setFieldsValue: this.setFieldsValue,
      getFieldValue: this.getFieldValue,
      registerEntity: this.registerEntity,
      submit: this.submit,
      setCallback: this.setCallback,
    };
  };
}

export default function useForm(form) {
  const formStore = useRef();
  if (!formStore.current) {
    if (form) {
      formStore.current = form;
    } else {
      const formInstance = new FormStore();
      formStore.current = formInstance.getForm();
    }
  }
  return [formStore.current];
}
